package main

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/thinkgos/gomodbus"
	"github.com/thinkgos/gomodbus/mb"
	"net/http"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

type MbParam struct{
	Addr byte 			`json:"Addr"`
	RegAddr uint16		`json:"RegAddr"`
	RegCnt uint16		`json:"RegCnt"`
	Data string         `json:"Data"`
}

type SerialParam struct{
	Name     string     `json:"Name"`
	BaudRate string 	`json:"BaudRate"`
	// Data bits: 5, 6, 7 or 8 (default 8)
	DataBits string		`json:"DataBits"`
	// Stop bits: 1 or 2 (default 1)
	StopBits string		`json:"StopBits"`
	// Parity: N - None, E - Even, O - Odd (default E)
	// (The use of no parity requires 2 stop bits.)
	Parity string       `json:"Parity"`
	//ms
	Timeout string      `json:"Timeout"`
}

type SerialAckParam struct{
	Code string			`json:"Code"`
	Message string		`json:"Message"`
	Data SerialParam	`json:"Data"`
}

type NetworkParam struct{
	Name string         `json:"Name"`
	DHCP string         `json:"DHCP"`
	IP string           `json:"IP"`
	Netmask string      `json:"Netmask"`
	Broadcast string    `json:"Broadcast"`
}

type NetworkAckParam struct{
	Code string			`json:"Code"`
	Message string		`json:"Message"`
	Data NetworkParam	`json:"Data"`
}

type TD200NetParamAckParam struct{
	Code    string					`json:"Code"`
	Message string					`json:"Message"`
	Data    threadModuleNetParam	`json:"Data"`
}

type FCURealDataAck struct{
	Code    string					`json:"Code"`
	Message string					`json:"Message"`
	Data    FCURealData				`json:"Data"`
}


type AckParam struct{
	Code string			`json:"Code"`
	Message string		`json:"Message"`
	Data string			`json:"Data"`
}

var client       *mb.Client
var mbParam      MbParam

var serialParam  = SerialParam{
	Name     : "/dev/ttyUSB1",
	BaudRate : "9600",
	DataBits : "8",
	StopBits : "1",
	Parity   : "N",
	Timeout  : "1000",
}
var networkParam = NetworkParam{
	Name      : "eth1",
	DHCP      : "1",
	IP        : "192.168.4.156",
	Netmask   : "255.255.255.0",
	Broadcast : "192.168.4.255",
}

func NewMbParam(addr byte,regAddr,regCnt uint16)*MbParam{
	return &MbParam{
		Addr   :addr,
		RegAddr:regAddr,
		RegCnt :regCnt,
	}
}

func main(){

	/**************获取参数************************/
	if serialParaRead(&serialParam) == true{
		fmt.Println(serialParam)
	}else{
		fmt.Println("read serialParam err")
		serialParaWrite(serialParam)
		fmt.Println(serialParam)
	}

	if networkParaRead(&networkParam) == true{
		fmt.Println(networkParam)
	}else{
		fmt.Println("read networkParam err")
		networkParaWrite(networkParam)
		fmt.Println(networkParam)
	}

	/**************网口初始化***********************/
	cmdSetIP()


	/**************串口初始化***********************/
	threadModuleOpenPort(serialParam.Name)


	/**************httpserver初始化****************/
	router := gin.Default()
	//router.Use(gin.Logger())

	router.Static("/css","webroot/css")
	router.Static("/images","webroot/images")
	router.Static("/js","webroot/js")
	router.Static("/json","webroot/json")
	router.Static("/layui","webroot/layui")
	router.Static("/myico","webroot/myico")
	router.Static("/page","webroot/page")

	router.GET("/", func(context *gin.Context) {
		context.File("webroot/index.html")
	})

	router.GET("/favicon.ico", func(context *gin.Context) {
		context.File("webroot/favicon.ico")
	})

	userRouter := router.Group("/api/v1/modbus")
	{
		userRouter.POST("/cmd03",apiReadHoldReg)

		userRouter.POST("/cmd10",apiWriteMultiReg)
	}

	networkRouter := router.Group("/api/v1/network/param")
	{
		networkRouter.POST("", apiSetNetwork)

		networkRouter.GET("", apiGetNetwork)
	}

	networkDHCPRouter := router.Group("/api/v1/network/dhcp")
	{
		networkDHCPRouter.POST("", apiSetNetwork)

		networkDHCPRouter.GET("", apiGetNetwork)
	}

	serialRouter := router.Group("/api/v1/serial/param")
	{
		serialRouter.POST("",apiSetSerial)

		serialRouter.GET("",apiGetSerial)
	}

	td200Router := router.Group("/api/v1/td200")
	{
		td200Router.GET("/netStatus",apiGetTD200NetStatus)

		td200Router.GET("/netParam",apiGetTD200NetParam)

		td200Router.POST("/netParam",apiSetTD200NetParam)

		td200Router.POST("/rtc",apiSetTD200RTC)
	}

	fcuRouter := router.Group("/api/v1/fcu")
	{
		fcuRouter.GET("/realData",apiGetFCURealData)

		fcuRouter.POST("/remoteCmdOpen",apiSetFCURemoteCmdOpen)

		fcuRouter.POST("/remoteCmdClose",apiSetFCURemoteCmdClose)

		fcuRouter.POST("/remoteCmdAdjust",apiSetFCURemoteCmdAdjust)
	}


	//router.Run()
	router.Run(":8090")

	//threadModuleReadNetStatus()
	//threadModuleReadNetParam()
	//threadModuleWriteNetParam(24,13361)
	//threadModuleReadNetParam()
	//threadModuleReadSoftVer()

	//threadModuleWriteRTC(threadModuleGetSystemRTC())
	//var buf =[]byte{0x01,0x02,0x03}
	//threadModuleWriteData(1,buf)
}

func mCmd(cmdStr string) string{
	cmd := exec.Command(cmdStr)
	var out bytes.Buffer
	cmd.Stdout = &out
	cmd.Run()

	str := out.String()  //

	return str
}

func cmdIfconfig() {

	strAddr := mCmd("ifconfig")
	fmt.Println(strAddr)
}

func cmdSetIP(){
	var strCmd string

	strCmd = "ifconfig" + " " + networkParam.Name + " " + networkParam.IP + " netmask " + networkParam.Netmask + " broadcast " +
		networkParam.Broadcast + " up"

	fmt.Println(strCmd)

	//mCmd(strCmd)
}

func FileExist(path string) bool {
	_, err := os.Lstat(path)
	return !os.IsNotExist(err)
}

func serialParaRead(param *SerialParam) bool{

	if FileExist("/opt/ibox/selfpara/serialpara.json") == true{
		fp, err := os.OpenFile("/opt/ibox/selfpara/serialpara.json", os.O_RDONLY, 0777)
		if err != nil {
			fmt.Println("open serialpara.json err",err)
			return false
		}
		defer fp.Close()

		data := make([]byte, 500)
		dataCnt, err := fp.Read(data)

		err = json.Unmarshal(data[:dataCnt],param)
		if err != nil{
			fmt.Println("serialpara unmarshal err",err)
		}
		return true
	}else{
		return false
	}
}

func serialParaWrite(param SerialParam){

	fp, err := os.OpenFile("/opt/ibox/selfpara/serialpara.json", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
	if err != nil {
		fmt.Println("open serialpara.json err",err)
		return
	}
	defer fp.Close()

	sJson,_ := json.Marshal(param)
	fmt.Println(string(sJson))

	_, err = fp.Write(sJson)
	if err != nil {
		fmt.Println("write serialpara.json err",err)
	}
}

func networkParaRead(param *NetworkParam) bool{

	if FileExist("/opt/ibox/selfpara/networkpara.json") == true {
		fp, err := os.OpenFile("/opt/ibox/selfpara/networkpara.json", os.O_RDONLY, 0777)
		if err != nil {
			fmt.Println("open networkpara.json err", err)
			return false
		}
		defer fp.Close()

		data := make([]byte, 500)
		dataCnt, err := fp.Read(data)

		err = json.Unmarshal(data[:dataCnt], param)
		if err != nil {
			fmt.Println("networkpara unmarshal err", err)
		}
		return true
	}else{
		return false
	}
}

func networkParaWrite(param NetworkParam){

	fp, err := os.OpenFile("/opt/ibox/selfpara/networkpara.json", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
	if err != nil {
		fmt.Println("open networkpara.json err",err)
	}
	defer fp.Close()

	sJson,_ := json.Marshal(param)
	fmt.Println(string(sJson))

	_, err = fp.Write(sJson)
	if err != nil {
		fmt.Println("write networkpara.json err",err)
	}
}

func apiReadHoldReg(context *gin.Context){

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)

	fmt.Println(string(bodyBuf[:n]))

	//获取读寄存器的参数
	rMbParam := &MbParam{}
	err := json.Unmarshal(bodyBuf[:n],rMbParam)
	if err != nil {
		fmt.Println("rMbParam json unMarshall err,",err)

		aParam := AckParam{
			Code:"1",
			Message:"json unMarshall err",
			Data:"",
		}
		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	mRegValue := mbParamReadHoldReg(rMbParam.Addr,rMbParam.RegAddr,rMbParam.RegCnt)
	fmt.Printf("mRegValue %#v\n",mRegValue)
	var sRegValue string = ""

	for i:=0;i<len(mRegValue);i++{
		sRegValue += strconv.FormatUint(uint64(mRegValue[i]),10)

		if i != (len(mRegValue)-1) {
			sRegValue = sRegValue + ","
		}else{
			sRegValue = sRegValue + ""
		}
	}
	fmt.Println(sRegValue)


	aParam := AckParam{
		Code:"0",
		Message:"",
		Data:"",
	}
	aParam.Data = sRegValue
	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))
}

func apiWriteMultiReg(context *gin.Context){

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)

	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rMbParam := &MbParam{}
	err := json.Unmarshal(bodyBuf[:n],rMbParam)
	if err != nil {
		fmt.Println("rMbParam json unMarshall err,",err)

		aParam := AckParam{
			Code:"1",
			Message:"json unMarshall err",
			Data:"",
		}
		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	//将字符串中数值取出来
	sData := strings.Split(rMbParam.Data,",")
	//fmt.Println(sData)
	bData := make([]byte,0)
	bData2 := make([]byte,2)
	for _,v:= range sData{
		//tByte,err := strconv.ParseUint(v,10,16)
		tByte,_:= strconv.Atoi(v)
		binary.BigEndian.PutUint16(bData2,uint16(tByte))

		bData = append(bData,bData2...)
	}
	fmt.Printf("bData is %d\n",bData)

	err = mbParamWriteMutilReg(rMbParam.Addr,rMbParam.RegAddr,
						 rMbParam.RegCnt,bData)
	if err != nil{
		aParam := AckParam{
			Code:"1",
			Message:"write reg timeout",
			Data:"",
		}
		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))

	}
	aParam := AckParam{
		Code:"0",
		Message:"",
		Data:"",
	}
	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))

}

func mbParamOpenPort(port string) bool{
	status := false

	//调用RTUClientProvider的构造函数,返回结构体指针
	p := modbus.NewRTUClientProvider()
	p.Address = port
	p.BaudRate = 115200
	p.DataBits = 8
	p.Parity = "N"
	p.StopBits = 1
	p.Timeout = 100 * time.Millisecond

	client = mb.NewClient(p)
	client.LogMode(true)
	err := client.Start()
	if err != nil {
		fmt.Println("start err,", err)
		return status
	}

	status = true
	return status
}

/**
	读保持寄存器
*/
func mbParamReadHoldReg(slaveAddr byte,regAddr uint16,regCnt uint16)[]uint16{
	value, err := client.ReadHoldingRegisters(slaveAddr, regAddr, regCnt)
	if err != nil {
		fmt.Println("readHoldErr,", err)
	} else {
		//fmt.Printf("%#v\n", value)
	}

	return value
}

/**
写多个寄存器
*/
func mbParamWriteMutilReg(slaveAddr byte,regAddr uint16,regCnt uint16,data []byte) error{
	err := client.WriteMultipleRegisters(slaveAddr,regAddr,regCnt,data)
	if err != nil {
		fmt.Println("writeMulRegErr,", err)
	}

	return err
}

func apiSetSerial(context *gin.Context){

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)

	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rSerialParam := &SerialParam{}
	err := json.Unmarshal(bodyBuf[:n],rSerialParam)
	if err != nil {
		fmt.Println("rSerialParam json unMarshall err,",err)

		aParam := AckParam{
			Code:"1",
			Message:"json unMarshall err",
			Data:"",
		}
		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	aParam := AckParam{
		Code:"0",
		Message:"",
		Data:"",
	}
	sJson,_ := json.Marshal(serialParam)
	aParam.Data = string(sJson)

	sJson,_ = json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))

}

func apiGetSerial(context *gin.Context){

	aParam := SerialAckParam{
		Code:"0",
		Message:"",
	}

	aParam.Data = serialParam

	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))
}

func apiSetNetwork(context *gin.Context){

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)

	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rNetworkParam := &NetworkParam{}
	err := json.Unmarshal(bodyBuf[:n],rNetworkParam)
	if err != nil {
		fmt.Println("rNetworkParam json unMarshall err,",err)

		aParam := AckParam{
			Code:"1",
			Message:"json unMarshall err",
			Data:"",
		}
		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	networkParam = *rNetworkParam

	aParam := AckParam{
		Code:"0",
		Message:"",
		Data:"",
	}
	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))

}

func apiGetNetwork(context *gin.Context){

	aParam := NetworkAckParam{
		Code:"0",
		Message:"",
	}

	aParam.Data = networkParam

	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))
}

func apiGetTD200NetStatus(context *gin.Context){

	aParam := AckParam{
		Code:"1",
		Message:"",
		Data:"",
	}

	if threadModuleReadNetStatus() == true{

		netStatus := threadModuleGetNodeNetStatus()

		var sNetStatus string = ""

		for i:=0;i<len(netStatus);i++{
			sNetStatus += fmt.Sprintf("%d",netStatus[i])
			if i != (len(netStatus)-1) {
				sNetStatus = sNetStatus + ","
			}else{
				sNetStatus = sNetStatus + ""
			}
		}
		//fmt.Println(sNetStatus)

		aParam.Code = "0"
		aParam.Data = sNetStatus
	}else{
		aParam.Code = "1"
		aParam.Message = "read err"
	}

	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))
}

func apiGetTD200NetParam(context *gin.Context) {

	aParam := TD200NetParamAckParam{
		Code:    "1",
		Message: "",
	}

	if threadModuleReadNetParam() == true {

		NetParam := threadModuleGetNetParam()

		aParam.Code = "0"
		aParam.Data = NetParam
	} else {
		aParam.Code = "1"
		aParam.Message = "read err"
	}

	sJson, _ := json.Marshal(aParam)

	context.String(http.StatusOK, string(sJson))
}

func apiSetTD200NetParam(context *gin.Context){

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)

	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rNetParam := &threadModuleNetParam{}
	err := json.Unmarshal(bodyBuf[:n],rNetParam)
	if err != nil {
		fmt.Println("rNetParam json unMarshall err,",err)

		aParam := AckParam{
			Code:"1",
			Message:"json unMarshall err",
			Data:"",
		}
		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	TD200NetParam = *rNetParam

	threadModuleWriteNetParam(TD200NetParam)

	aParam := AckParam{
		Code:"0",
		Message:"",
		Data:"",
	}
	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))

}

func apiSetTD200RTC(context *gin.Context){

	aParam := AckParam{
		Code:"1",
		Message:"",
		Data:"",
	}

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)
	fmt.Println(string(bodyBuf[:n]))

	rtc := threadModuleGetSystemRTC()
	if threadModuleWriteRTC(rtc) == true{
		aParam.Code = "0"
	}else{

	}

	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))

}

func apiGetFCURealData(context *gin.Context) {

	aParam := FCURealDataAck{
		Code:    "1",
		Message: "",
	}

	if FCUGetRealData(0x01) == true {
		aParam.Code = "0"
		aParam.Data = fcuRealData
	} else {
		aParam.Code = "1"
		aParam.Message = "read err"
	}

	sJson, _ := json.Marshal(aParam)

	context.String(http.StatusOK, string(sJson))
}

func apiSetFCURemoteCmdOpen(context *gin.Context){

	aParam := AckParam{
		Code:"1",
		Message:"",
		Data:"",
	}

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)
	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rRemoteCmd := &struct{
		Addr byte
	}{}
	err := json.Unmarshal(bodyBuf[:n],rRemoteCmd)
	if err != nil {
		fmt.Println("rRemoteCmd json unMarshall err,",err)

		aParam.Code = "1"
		aParam.Message = "json unMarshall err"

		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	if FCUSetRemoteCmd(rRemoteCmd.Addr,1) == true{
		aParam.Code = "0"

	}else{
		aParam.Code = "1"
		aParam.Message = "device timeout"
	}

	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))
}

func apiSetFCURemoteCmdClose(context *gin.Context){

	aParam := AckParam{
		Code:"1",
		Message:"",
		Data:"",
	}

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)
	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rRemoteCmd := &struct{
		Addr byte
	}{}
	err := json.Unmarshal(bodyBuf[:n],rRemoteCmd)
	if err != nil {
		fmt.Println("rRemoteCmd json unMarshall err,",err)

		aParam.Code = "1"
		aParam.Message = "json unMarshall err"

		sJson,_ := json.Marshal(aParam)

		context.String(http.StatusOK,string(sJson))
		return
	}

	if FCUSetRemoteCmd(rRemoteCmd.Addr,0) == true{
		aParam.Code = "0"

	}else{
		aParam.Code = "1"
		aParam.Message = "device timeout"
	}

	sJson,_ := json.Marshal(aParam)

	context.String(http.StatusOK,string(sJson))
}

func apiSetFCURemoteCmdAdjust(context *gin.Context){

	aParam := AckParam{
		Code:"1",
		Message:"",
		Data:"",
	}

	bodyBuf := make([]byte,1024)
	n,_ := context.Request.Body.Read(bodyBuf)
	fmt.Println(string(bodyBuf[:n]))

	//获取写寄存器的参数
	rRemoteCmd := &struct{
		Addr  byte
		Mode  byte  //模式
		Temp  byte  //温度
	}{}
	err := json.Unmarshal(bodyBuf[:n],rRemoteCmd)
	if err != nil {
		fmt.Println("rRemoteCmd json unMarshall err,",err)

		aParam.Code = "1"
		aParam.Message = "json unMarshall err"

		sJson,_ := json.Marshal(aParam)
		context.String(http.StatusOK,string(sJson))
		return
	}

	tCmd := uint16(rRemoteCmd.Mode)*256+uint16(rRemoteCmd.Temp)
	if FCUSetRemoteCmd(rRemoteCmd.Addr,tCmd) == true{
		aParam.Code = "0"

	}else{
		aParam.Code = "1"
		aParam.Message = "device timeout"
	}

	sJson,_ := json.Marshal(aParam)
	context.String(http.StatusOK,string(sJson))
}